<template>
	<view class="VideoChat">
		<view class="medias">
			<view class="meida" :class="{active:activeIndex === index}" v-for="(item,index) in videoInputList"
				:key=index @click="changCamera(index)">{{item.label}}</view>
			<!-- view class="meida" :class="{active:activeIndex === index}"
				v-for="(item,index) in videoInputList">{{item.label}}
		</view> -->
	</view>
	<view class="video">
		<!-- 服了uniapp的video封装了,导致无法获取原生的video进行数据流赋值,害我为他踌躇了一天,太难受了 -->
		<video id="remoteVideo" autoplay playsinline></video>
		<view class="left">
			<video id="localVideo" autoplay playsinline></video>
			<canvas  canvas-id="firstCanvas" id="firstCanvas"></canvas>
		</view>
			<!-- 可以不需要 -->
			<!-- <source :src="videoUrl" type="video/mp4" /> -->
		<a id="downLoadLink" style="display: none;"></a>
		<!-- canvas画布 -->
		<!-- style="width: 300px; height: 200px;" -->
	</view>
	<view class="CameraButton">
		<button @click="createOffer" ref="offerSdp" class="OpenVideo func" v-if="!this.chat">连接</button>
		<button @click="leave" v-if="this.chat" class="leave func">离开</button>
		<button @click="openScreen" v-if="!this.screen" class="openScreen func">屏幕共享</button>
		<button @click="closeScreen" v-if="this.screen" class="closeScreen func">取消屏幕</button>
		<!-- <button @click="recordOrStop" v-if="!isRecord" class="recordOrStop func">录制视频</button> -->
	</view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				user: {
					id: '',
					username: '',
				},
				chat: false,
				screen: false,
				videoInputList: [],
				deviceId: '',
				peerConnection: null,
				localVideo: null,
				remoteVideo: null,
				displayStream: null,
				localStream: null,
				remoteStream: null,
				offerSdp: null,
				answerSdp: null,
				isRecord: false,
				activeIndex: 0
			}
		},
		onReady: function(e) {
			//canvas画布绘画
			var context = uni.createCanvasContext('firstCanvas')
			context.setStrokeStyle("#ffff7f")
			context.setLineWidth(5)
			// context.rect(0, 0, 200, 200)
			context.stroke()
			context.setStrokeStyle("#000000")
			context.setLineWidth(2)
			context.moveTo(160, 100)
			context.arc(100, 100, 60, 0, 2 * Math.PI, true)
			context.moveTo(140, 100)
			context.arc(100, 100, 40, 0, Math.PI, false)
			context.moveTo(85, 80)
			context.arc(80, 80, 10, 0, 2 * Math.PI, true)
			context.moveTo(125, 80)
			context.arc(120, 80, 10, 0, 2 * Math.PI, true)
			context.stroke()
			context.draw()
		},
		onLoad(option) {

			uni.removeStorageSync("isVideo");
			this.screen = uni.getStorageSync("screen");
			console.log("this.screen");
			console.log(this.screen);
			this.user.id = option.id;
			this.user.username = option.username;
			console.log(option.username);
			uni.setNavigationBarTitle({
				title: this.user.username
			})
			uni.setNavigationBarColor({
				frontColor: "#000000",
				backgroundColor: '#00b4b3'
			});
			this.openSocket();
			navigator.mediaDevices.enumerateDevices().then((devices) => {
				devices.forEach((device) => {
					if (device.kind == "videoinput") {
						this.videoInputList.push(device);
					}
				})
			});
			// this.deviceId = this.videoInputList[1].deviceId
			this.onOpenCamera();
		},
		onShow() {
			this.chat = uni.getStorageSync('isVideo');
			this.screen = uni.getStorageSync('screen');
		},
		onUnload() {
			uni.setStorageSync("screen", false);
			this.leave();
			uni.closeSocket({})
			console.log("关闭了当前对话...")
		},

		methods: {
			canvasIdErrorCallback: function(e) {
				console.error(e.detail.errMsg)
			},
			chang(e) {
				console.log(e);
			},
			async handleSuccess(stream) {
				this.peerConnection = new RTCPeerConnection();
				//显示用户自己
				this.localVideo = document.getElementById('localVideo').firstChild.firstChild;
				// 显示他人
				this.remoteVideo = document.getElementById('remoteVideo').firstChild.firstChild;
				// 本地摄像头
				this.localStream = await navigator.mediaDevices.getUserMedia({
					video: {
						deviceId: this.deviceId
					},
					audio: true
				})
				// 他人摄像头
				this.remoteStream = new MediaStream();

				if (this.screen) {
					// 屏幕
					uni.showModal({
						title: "屏幕共享",
						content: "是否开启屏幕共享",
						success: async (res) => {
							if (res.confirm) {
								console.log("确认开启屏幕共享");
								this.$u.toast("已开启")
								this.displayStream = await navigator.mediaDevices.getDisplayMedia();
								this.localVideo.srcObject = this.displayStream

								this.remoteVideo.srcObject = this.remoteStream

								this.displayStream.getTracks().forEach((track) => {
									this.peerConnection.addTrack(track, this.displayStream);
								});
							} else if (res.cancel) {
								uni.setStorageSync("screen", false);
								uni.sendSocketMessage({
									data: JSON.stringify({
										type: 'closeScreen',
										data: '取消共享'
									})
								})
								location.reload()
								this.$u.toast("关闭屏幕共享")
							}
						}
					})

				} else {
					this.localVideo.srcObject = this.localStream

					this.remoteVideo.srcObject = this.remoteStream

					this.localStream.getTracks().forEach((track) => {
						this.peerConnection.addTrack(track, this.localStream);
					});
				}


				this.peerConnection.ontrack = (event) => {
					event.streams[0].getTracks().forEach((track) => {
						this.remoteStream.addTrack(track);
					});
				};
				console.log(this.peerConnection);
			},
			async createOffer() {
				if (uni.getStorageSync("isVideo")) {
					this.$u.toast("当前已通话！");
				} else {
					this.peerConnection.onicecandidate = async (event) => {
						//创建新的选件 ICE 候选项时触发的事件
						if (event.candidate) {
							let data = {};
							data.to = this.user.username;
							data.from = uni.getStorageSync('user').username;;
							data.type = this.peerConnection.localDescription.type;
							data.sdp = this.peerConnection.localDescription.sdp;
							uni.sendSocketMessage({
								data: JSON.stringify(data)
							})
						}
					};
					const offer = await this.peerConnection.createOffer();
					await this.peerConnection.setLocalDescription(offer);
				}

			},
			async createAnswer() {
				let offer = this.offerSdp
				this.peerConnection.onicecandidate = async (event) => {
					//创建新答案 ICE 候选项时触发的事件
					if (event.candidate) {
						console.log('Adding answer candidate...:', event.candidate);

						let data = {};
						data.to = this.user.username;
						data.from = uni.getStorageSync('user').username;
						data.type = this.peerConnection.localDescription.type;
						data.sdp = this.peerConnection.localDescription.sdp;

						uni.sendSocketMessage({
							data: JSON.stringify(data)
						})
					}
				};

				await this.peerConnection.setRemoteDescription(offer);

				let answer = await this.peerConnection.createAnswer();
				await this.peerConnection.setLocalDescription(answer);
			},
			async addAnswer() {
				console.log('Add answer triggerd')
				let answer = this.answerSdp;
				console.log('answer:', answer)
				if (!this.peerConnection.currentRemoteDescription) {
					this.peerConnection.setRemoteDescription(answer);
					this.chat = true;
					uni.setStorageSync("isVideo", true);
					uni.sendSocketMessage({
						data: JSON.stringify({
							type: '0',
							msg: '通话成功'
						})
					});
				}
			},

			onOpenCamera(e) {
				// 约束条件
				const constraints = {
					audio: true,
					video: {
						facingMode: "user", // 使用前置摄像头
						width: 880, // 宽度为 640 像素
						height: 480, // 高度为 480 像素
						frameRate: 90, // 帧率为 30 帧每秒
					}
				};
				navigator.mediaDevices.getUserMedia(constraints).then(
					this.handleSuccess
				).catch(
					null
				);
			},
			changCamera(id) {
				this.activeIndex = id;
				console.log(id);
				// uni.setStorageSync("deviceId", this.videoInputList[id].deviceId);
				this.deviceId = this.videoInputList[id].deviceId;
				console.log(this.deviceId);
				this.onOpenCamera();
				// this.createOffer();
				uni.sendSocketMessage({
					data: JSON.stringify({
						type: 'changCamera',
						data: '更改摄像头'
					})
				})
				if (uni.getStorageSync("isVideo")) {
					this.$u.toast("等待一秒后,重新建立连接！");
				}
				// this.reload();
			},
			openScreen() {
				uni.setStorageSync("screen", true);
				console.log("screen", screen);
				uni.sendSocketMessage({
					data: JSON.stringify({
						type: 'openScreen',
						data: '屏幕共享'
					})
				})
				location.reload()
			},
			closeScreen() {
				uni.setStorageSync("screen", false);
				console.log("screen", screen);
				uni.sendSocketMessage({
					data: JSON.stringify({
						type: 'closeScreen',
						data: '取消共享'
					})
				})
				location.reload()
			},
			leave() {
				uni.sendSocketMessage({
					data: JSON.stringify({
						type: '-2',
						msg: '对方退出聊天'
					})
				});
				location.reload()
				setTimeout(() => {
					this.$u.toast('当前已离开！！请在一秒后连接')
				}, 1000);

			},
			openSocket() {
				uni.connectSocket({
					url: 'ws://localhost:3000/webRTC'
				});
				uni.onSocketError(function(res) {
					console.log('WebSocket连接打开失败，请检查！');
				});
				uni.onSocketOpen((res) => {
					console.log('WebSocket连接已打开！');
				});
				uni.onSocketMessage((res) => {
					console.log("有新消息！");
					var obj = JSON.parse(res.data);
					console.log("obj");
					console.log(obj);
					let {
						type,
						sdp,
						from,
						to,
						msg
					} = JSON.parse(res.data);
					console.log("from,to");
					console.log(from, to);
					switch (type) {
						case 'offer':
							// 用于视频连接，接受offer dsp
							console.log('offer');
							// if (to == uni.getStorageSync('user').username) {
							// 	console.log(uni.getStorageSync('user').username);
							this.offerSdp = {
								type,
								sdp
							};
							uni.showModal({
								title: from + "请求视频通话",
								content: '是否同意建立通话',
								duration: 3000,
								success: (res) => {
									if (res.confirm) {
										console.log('用户点击确认');
										this.createAnswer();
										uni.showLoading({
											title: '加载中'
										})
										setTimeout(function() {
											uni.hideLoading();
										}, 500);
									} else if (res.cancel) {
										uni.sendSocketMessage({
											data: JSON.stringify({
												type: 'cancel',
												msg: to + "拒绝了你的视频请求"
											})
										})
										console.log('用户点击取消')
										location.reload()
									}
								}

							});
							// } 
							// else {
							// 	console.log("用户出错了")
							// }
							break;
						case 'answer':
							// 用于视频连接，接受answer dsp
							// console.log('answer');
							// if (to == uni.getStorageSync('user').username) {
							// 	console.log(uni.getStorageSync('user').username);
							this.answerSdp = {
								type,
								sdp
							};
							this.addAnswer();
							// }
							break;
						case 'changCamera':
							console.log("changCamera");
							if (uni.getStorageSync('isVideo')) {
								this.$u.toast('对方更换摄像头，请重新连接！！页面一秒后更新');
								setTimeout(() => {
									location.reload()
								}, 1000);
							}

							// this.reload()
							break;
						case 'openScreen':
							console.log("openScreen");
							if (uni.getStorageSync('screen')) {
								this.$u.toast('对方请求屏幕共享，请重新连接！！页面一秒后更新');
								setTimeout(() => {
									location.reload()
								}, 1000);
							}

							// this.reload()
							break;
						case 'closeScreen':
							console.log("closeScreen");
							if (!uni.getStorageSync('screen')) {
								this.$u.toast('对方关闭屏幕共享，请重新连接！！页面一秒后更新');
								setTimeout(() => {
									location.reload()
								}, 1000);
							}

							// this.reload()
							break;
						case 'cancel':
							console.log(to + "拒绝了你的视频请求");
							uni.showModal({
								title: msg,
								success: (res) => {
									location.reload()
								}
							})

							// this.reload()
							break;
						case '-1':
							console.log(msg);
							this.$u.toast('对方当前不在线，请稍后在拨打！！页面两秒后更新');
							setTimeout(() => {
								location.reload()
							}, 2000);
							break;
						case '-2':
							console.log(msg);
							this.$u.toast('对方当前已离开！！页面一秒后更新');
							setTimeout(() => {
								location.reload()
							}, 1000);
							break;
						case '0':
							console.log("通话建立成功");
							uni.setStorageSync("isVideo", true);
							this.chat = true;
						default:
							console.log("消息处理完成")
					}


				})
			},
			// // 录制或暂停
			// async recordOrStop() {

			// 	uni.showToast({
			// 		title: "开始录制",
			// 		duration: 1000
			// 	});
			// 	console.log('record');
			// 	this.isRecord = !this.isRecord;
			// 	var recordedBlobs = [];
			// 	const stream = await navigator.mediaDevices.getDisplayMedia();
			// 	var mediaRecorder = new MediaRecorder(stream, {
			// 		mimeType: 'video/webm; codecs=vp9'
			// 	});
			// 	mediaRecorder.start();
			// 	// 视频录制监听事件
			// 	mediaRecorder.ondataavailable = e => {
			// 		console.log(e);
			// 		// 录制的视频数据有效
			// 		if (e.data && e.data.size > 0) {
			// 			recordedBlobs.push(e.data);
			// 		}
			// 	};
			// 	console.log("有效");
			// 	// 停止录像后增加下载视频功能，将视频流转为mp4格式
			// 	mediaRecorder.onstop = () => {
			// 		const blob = new Blob(recordedBlobs, {
			// 			type: 'video/mp4'
			// 		});
			// 		// document.getElementById('displayVideo').firstChild.firstChild.src = window.URL.createObjectURL(blob);
			// 		this.recordedBlobs = [];
			// 		// 将视频链接转换完可以用于在浏览器上预览的本地视频
			// 		const videoUrl = window.URL.createObjectURL(blob);
			// 		console.log(videoUrl);
			// 		// 设置下载链接
			// 		document.getElementById('downLoadLink').href = videoUrl;
			// 		// 设置下载mp4格式视频
			// 		document.getElementById('downLoadLink').download = 'media.mp4';
			// 		// 生成随机数字
			// 		const rand = Math.floor((Math.random() * 1000000));
			// 		// 生成视频名
			// 		const name = `video${rand}.mp4`;
			// 		// setAttribute() 方法添加指定的属性，并为其赋指定的值
			// 		document.getElementById('downLoadLink').setAttribute('download', name);
			// 		// 0.5s后自动下载视频
			// 		setTimeout(() => {
			// 			document.getElementById('downLoadLink').click();
			// 		}, 500);
			// 		this.isRecord = !this.isRecord;
			// 		uni.showToast({
			// 			title: "已停止录制",
			// 			duration: 1000
			// 		});
			// 	}
			// },
		}
	}
</script>

<style lang="scss" scoped>
	.VideoChat {
		width: 100%;
		height: 100vh;

		.video {
			// top: 50rpx;
			width: 100%;
			height: 100%;
			display: flex;
			flex-direction: row-reverse;
			position: relative;
			background-image: linear-gradient(-225deg, #77FFD2 0%, #6297DB 48%, #1EECFF 100%);

			#localVideo {
				width: 100%;
				height: 60%;
				z-index: 5;
				
				// margin: 0px 20rpx;s
			}
			.left{
				position: relative;
				left: 0rpx;
				width: 20%;
				height: 60%;
			}
			#remoteVideo {
				width: 80%;
				height: 100%;
				position: relative;
				z-index: 5;
				
				
			}
			#firstCanvas{
				top: 10%;
				left: -23rpx;
				width: 120%;
				height: 25vh;
				// background-color: #333;
				-webkit-animation: rotate-center 0.6s ;
				        animation: rotate-center 0.6s ;
			}
			#firstCanvas:active{
				top: 10%;
				left: -23rpx;
				width: 120%;
				height: 25vh;
				z-index: 999;
				        animation: none ;
			}

		}

		.medias {
			width: 100%;
			// height: 10%;
			z-index: 99;

			.meida {
				background-color: whitesmoke;
				height: 40px;
				width: 100%;
				background-color: blanchedalmond;
				&.active {
					background-color: orange;
					height: 40px;
					width: 100%;
					border-color: #333;
					border-radius: 10rpx;
					font-weight: bold;
					box-shadow: 0 0 5rpx 1rpx #999;
					z-index: 999;
				}
			}
		}

		.CameraButton {
			width: 100%;
			height: 20%;
			position: relative;
			top: 0rpx;
			display: flex;
			flex-direction: row;
			bottom: 0rpx;
			justify-content: center;
			background-image: linear-gradient(-225deg, #77FFD2 0%, #6297DB 48%, #1EECFF 100%);

			.func {
				background-color: $boss-base-color;
				border-radius: 30rpx;
				width: 200rpx;
				height: 100rpx;
				margin: 10rpx 30rpx;
				padding: 20rpx;
				font-size: 24rpx;
				z-index: 99;
				font-size: 30rpx;
				line-height: 60rpx;
				font-weight: bold;
			}

			.func:hover {
				background-color: $boss-base-color;
				border-radius: 30rpx;
				width: 200rpx;
				height: 100rpx;
				margin: 10rpx 30rpx;
				padding: 20rpx;
				font-size: 24rpx;
				z-index: 99;
				font-size: 30rpx;
				line-height: 60rpx;
				font-weight: bold;
				background-color: rgba(30, 252, 255, 1.0);
				-webkit-box-shadow: 10px 10px 99px 6px rgba(30, 252, 255, 1.0);
				-moz-box-shadow: 10px 10px 99px 6px rgba(30, 252, 255, 1.0);
				box-shadow: 10px 10px 99px 6px rgba(30, 252, 255, 1.0);
			}
		}
	}
</style>